/*******************************************************************************
 * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *   
 * The Eclipse Public License is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * The Eclipse Distribution License is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *   
 * Contributors:
 * Bosch Software Innovations GmbH - Please refer to git log
 *******************************************************************************/
package org.eclipse.vorto.codegen.coap.server.templates

import org.eclipse.emf.common.util.EList
import org.eclipse.emf.common.util.EMap
import org.eclipse.vorto.codegen.api.ITemplate
import org.eclipse.vorto.codegen.api.InvocationContext
import org.eclipse.vorto.codegen.coap.CoAPUtils
import org.eclipse.vorto.codegen.utils.Utils
import org.eclipse.vorto.core.api.model.datatype.Property
import org.eclipse.vorto.core.api.model.functionblock.FunctionblockModel
import org.eclipse.vorto.core.api.model.informationmodel.FunctionblockProperty
import org.eclipse.vorto.core.api.model.informationmodel.InformationModel

class CoAPServerTemplate implements ITemplate<InformationModel>{
	
	private String className;
	private String interfaceName;
	private String packageName;
	private String imports;
	
	new(
		String className,
		String classPackage,
		String interfaceName,
		String imports
	) {
		this.className = className;
		this.packageName = classPackage;
		this.interfaceName = interfaceName;
		this.imports = imports;
	}
	
	override getContent(InformationModel im,InvocationContext invocationContext) {
		'''
			/*
			*****************************************************************************************
			* The present code has been generated by the Eclipse Vorto CoAP Code Generator.
			*
			* The basis for the generation was the Information Model which is uniquely identified by:
			* Name:				«im.name»
			* Namespace:	«im.namespace»
			* Version:		«im.version»
			*****************************************************************************************
			*/
			
			package «this.packageName»;
			
			import «imports».*;
			import org.eclipse.californium.core.CoapServer;
			
			public class «className.toFirstUpper» extends CoapServer {
				
				/**
				* Constructor for a new CoAP server providing resources which are specified 
				* in the given Information Model.
				*/
				public «className.toFirstUpper»(«interfaceName» handler) {
				
					final boolean VISIBLE = true;
					final boolean NOT_VISIBLE = false;
					final boolean GET = true;
					final boolean PUT = true;
					final boolean POST = true;
					final boolean DELETE = true;
					final boolean DISCOVER = true;
					final boolean OBSERVE = true;
					
					«val EMap<FunctionblockModel, EList<FunctionblockProperty>> map = CoAPUtils.sortByPropertyType(im.properties)»
					«FOR resource : map.keySet»
						add(new Link("«resource.name.toFirstLower»"){{
								setVisible(VISIBLE);
								getAttributes().addAttribute("title", "«resource.description» ");
						}}
						«var EList<FunctionblockProperty> instances = map.get(resource)»
							«FOR instance : instances»
								.add(new Link("«instance.name.toFirstLower»"){{
										setVisible(NOT_VISIBLE);
										getAttributes().addAttribute("title", "«instance.description» ");
								}}
								«IF instance.type.functionblock.operations!=null»
									«FOR operation: instance.type.functionblock.operations»
										.add(new Resource("«operation.name.toFirstLower»",
											new Resource.Configuration(false, false, POST, false, false, false),
											handler){{
												setVisible(NOT_VISIBLE);
												getAttributes().addAttribute("title", "«operation.description» ");
											}})
									«ENDFOR»
								«ENDIF»
								«IF instance.type.functionblock.events!=null»
									«FOR event: instance.type.functionblock.events»
										.add(new Resource("«event.name.toFirstLower»",
											new Resource.Configuration(false, false, false, false, false, OBSERVE),
											handler){{
												setVisible(NOT_VISIBLE);
												getAttributes().addAttribute("obs", "");
												
											}})
									«ENDFOR»
								«ENDIF»
								«IF instance.type.functionblock.status!=null»
									«FOR status : instance.type.functionblock.status.properties»
										.add(new Resource("«status.name.toFirstLower»",
											«this.getResourceConfiguration(status)»,
											handler){{
												setVisible(NOT_VISIBLE);
												getAttributes().addAttribute("title", "«status.description» ");
												«IF CoAPUtils.isEventable(status)»
													getAttributes().addAttribute("obs", "");
												«ENDIF»
											}})
									«ENDFOR»
								«ENDIF»
								)
							«ENDFOR»
						);
					«ENDFOR»
				}
			}
		'''
	}
	
	def private String getResourceConfiguration(Property property){
		var readable = "false"
		var writeable = "false"
		var eventable = "false"
		var result = "new Resource.Configuration("
		if (CoAPUtils.isReadable(property)) {
			readable = "GET";
		}
		if (CoAPUtils.isWritable(property)) {
			writeable = "PUT";
		}
		if (CoAPUtils.isEventable(property)){
			eventable = "OBSERVE";
		}
		return result + readable + ", " + writeable + ", false, false, false, " + eventable + ")";
	}
}